package net.aiion.weave;

import net.aiion.weave.asm.ClassWriter;
import net.aiion.weave.asm.FieldVisitor;
import net.aiion.weave.asm.MethodVisitor;
import net.aiion.weave.asm.Opcodes;
import net.aiion.weave.asm.Type;

public class T implements Opcodes
{
    public static byte[] dump() throws Exception {
        ClassWriter cw = new ClassWriter(0);
        FieldVisitor fv;
        MethodVisitor mv;

        cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "net/aiion/weave/A", null, "java/lang/Object", new String[0]);
        
        {
        	fv = cw.visitField(ACC_PUBLIC, "foo", "Ljava/lang/String;", null, null);
        	fv.visitEnd();
        }

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", null, null);
            mv.visitCode();
            
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKESTATIC, "net/aiion/weave/MainProgram", "print", "(Ljava/lang/String;)V");

            mv.visitVarInsn(ALOAD, 2);
            mv.visitMethodInsn(INVOKESTATIC, "net/aiion/weave/MainProgram", "print", "(Ljava/lang/String;)V");
            
            mv.visitInsn(RETURN);
            mv.visitMaxs(1, 3);
            mv.visitEnd();
        }
        
        {
        	mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Lnet/aiion/weave/S;)V", null, null);
        	mv.visitCode();
        	
        	mv.visitIntInsn(ALOAD, 0);
        	mv.visitLdcInsn("Foo!");
        	mv.visitFieldInsn(PUTFIELD, "net/aiion/weave/A", "foo", "Ljava/lang/String;");
        	
        	mv.visitLdcInsn(Type.getObjectType("net/aiion/weave/A"));
        	mv.visitIntInsn(BIPUSH, 2);
        	mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
        	
        	mv.visitInsn(DUP);
        	mv.visitInsn(ICONST_0);
        	mv.visitLdcInsn(Type.getType(String.class));
        	mv.visitInsn(AASTORE);
        	
        	mv.visitInsn(DUP);
        	mv.visitInsn(ICONST_1);
        	mv.visitLdcInsn(Type.getType(String.class));
        	mv.visitInsn(AASTORE);
        	
    		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getDeclaredConstructor", "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;");
    		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Constructor", "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;");
    		mv.visitIntInsn(ASTORE, 2);
    		
        	mv.visitVarInsn(ALOAD, 0);
        	
        	mv.visitVarInsn(ALOAD, 1);
        	mv.visitVarInsn(ALOAD, 2);
        	mv.visitInsn(ICONST_0);
        	mv.visitInsn(AALOAD);
        	mv.visitMethodInsn(INVOKEVIRTUAL, "net/aiion/weave/S", "get", "([Ljava/lang/annotation/Annotation;)Ljava/lang/String;");
        	
        	mv.visitVarInsn(ALOAD, 1);
        	mv.visitVarInsn(ALOAD, 2);
        	mv.visitInsn(ICONST_1);
        	mv.visitInsn(AALOAD);
        	mv.visitMethodInsn(INVOKEVIRTUAL, "net/aiion/weave/S", "get", "([Ljava/lang/annotation/Annotation;)Ljava/lang/String;");
        	
        	mv.visitMethodInsn(INVOKESPECIAL, "net/aiion/weave/A", "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
        	
        	mv.visitInsn(RETURN);
        	mv.visitMaxs(7, 3);
        	mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}
